package cn.acheng1314.im.common.session;

import cn.acheng1314.im.common.model.MessageBean;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;

import java.io.Serializable;
import java.net.SocketAddress;
import java.util.Objects;

/**
 * session
 */
public class ImSession implements Serializable {

    private transient static final long serialVersionUID = 1L;

    public transient static String HOST = "HOST";
    public transient static final int STATE_ENABLED = 0;
    public transient static final int STATE_DISABLED = 1;
    public transient static final int APNS_ON = 1;
    public transient static final int APNS_OFF = 0;

    public transient static String CHANNEL_IOS = "ios";
    public transient static String CHANNEL_ANDROID = "android";
    public transient static String CHANNEL_WINDOWS = "windows";

    private transient Channel session;

    /**
     * 数据库主键ID
     */
    private Long id;

    /**
     * session绑定的用户账号
     */
    private String account;

    /**
     * session在本台服务器上的ID
     */
    private String nid;

    /**
     * 客户端ID (设备号码+应用包名),ios为deviceToken
     */
    private String deviceId;

    /**
     * session绑定的服务器IP
     */
    private String host;

    /**
     * 终端设备类型
     */
    private String channel;

    /**
     * 终端设备型号
     */
    private String deviceModel;

    /**
     * 终端应用版本
     */
    private String clientAppVersion;

    /**
     * 终端系统版本
     */
    private String clientSystemVersion;

    /**
     * 登录时间
     */
    private Long loginTime;

    /**
     * 经度
     */
    private Double longitude;

    /**
     * 维度
     */
    private Double latitude;

    /**
     * 位置
     */
    private String location;

    /**
     * APNs推送状态
     */
    private int apns;

    /**
     * 状态
     */
    private int state;

    public ImSession(Channel session) {
        this.session = session;
        this.nid = session.id().asShortText();
    }


    public ImSession() {

    }


    public void setAttribute(String key, Object value) {
        if (session != null) {
            session.attr(AttributeKey.valueOf(key)).set(value);
        }
    }

    public boolean containsAttribute(String key) {
        if (session != null) {
            return session.hasAttr(AttributeKey.valueOf(key));
        }
        return false;
    }

    public Object getAttribute(String key) {
        if (session != null) {
            return session.attr(AttributeKey.valueOf(key)).get();
        }
        return null;
    }

    public void removeAttribute(String key) {
        if (session != null) {
            session.attr(AttributeKey.valueOf(key)).set(null);
        }
    }

    public SocketAddress getRemoteAddress() {
        if (session != null) {
            return session.remoteAddress();
        }
        return null;
    }


    public void write(MessageBean data) {

        if (session == null || !session.isActive()) {
            return;
        }

        session.writeAndFlush(data);
    }

    public boolean isConnected() {
        return (session != null && session.isActive()) || state == STATE_ENABLED;
    }

    public void closeNow() {
        if (session != null) {
            session.close();
        }
    }

    public void closeOnFlush() {
        if (session != null) {
            session.close();
        }
    }

    public boolean isIOSChannel() {
        return Objects.equals(channel, CHANNEL_IOS);
    }

    public boolean isAndroidChannel() {
        return Objects.equals(channel, CHANNEL_ANDROID);
    }

    public boolean isWindowsChannel() {
        return Objects.equals(channel, CHANNEL_WINDOWS);
    }

    public boolean isApnsEnable() {
        return Objects.equals(apns, APNS_ON);
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof ImSession) {
            ImSession target = (ImSession) o;
            return Objects.equals(target.deviceId, deviceId) && Objects.equals(target.nid, nid)
                    && Objects.equals(target.host, host);
        }
        return false;
    }

    @Override
    public String toString() {
        return "ImSession{" +
                "session=" + session.id().asLongText() +
                ", id=" + id +
                ", account='" + account + '\'' +
                ", nid='" + nid + '\'' +
                ", deviceId='" + deviceId + '\'' +
                ", host='" + host + '\'' +
                ", channel='" + channel + '\'' +
                ", deviceModel='" + deviceModel + '\'' +
                ", clientAppVersion='" + clientAppVersion + '\'' +
                ", clientSystemVersion='" + clientSystemVersion + '\'' +
                ", loginTime=" + loginTime +
                ", longitude=" + longitude +
                ", latitude=" + latitude +
                ", location='" + location + '\'' +
                ", apns=" + apns +
                ", state=" + state +
                '}';
    }

    public Channel getSession() {
        return session;
    }

    public void setSession(Channel session) {
        this.session = session;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getNid() {
        return nid;
    }

    public void setNid(String nid) {
        this.nid = nid;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getChannel() {
        return channel;
    }

    public void setChannel(String channel) {
        this.channel = channel;
    }

    public String getDeviceModel() {
        return deviceModel;
    }

    public void setDeviceModel(String deviceModel) {
        this.deviceModel = deviceModel;
    }

    public String getClientAppVersion() {
        return clientAppVersion;
    }

    public void setClientAppVersion(String clientAppVersion) {
        this.clientAppVersion = clientAppVersion;
    }

    public String getClientSystemVersion() {
        return clientSystemVersion;
    }

    public void setClientSystemVersion(String clientSystemVersion) {
        this.clientSystemVersion = clientSystemVersion;
    }

    public Long getLoginTime() {
        return loginTime;
    }

    public void setLoginTime(Long loginTime) {
        this.loginTime = loginTime;
    }

    public Double getLongitude() {
        return longitude;
    }

    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }

    public Double getLatitude() {
        return latitude;
    }

    public void setLatitude(Double latitude) {
        this.latitude = latitude;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public int getApns() {
        return apns;
    }

    public void setApns(int apns) {
        this.apns = apns;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }
}
